/**
 * @author  RR42 <im.razzy@gmail.com>
 * @version 0.1
 *
 * @section LICENSE
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details at
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @section DESCRIPTION
 *
 * This is a library for GTK+2 su/sudo frontends
 */

#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

/**
 * This shows dialog with OK button and title
 * @param message: title
 * @author RR42
 */

void gmessage(char* message) {
    GtkWidget* dialog = gtk_dialog_new_with_buttons (message,
        NULL,
        GTK_DIALOG_DESTROY_WITH_PARENT,
        GTK_STOCK_OK,
        GTK_RESPONSE_NONE,
        NULL);
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
}

/**
 * If key [ENTER] released, exit dialog with GTK_RESPONSE_OK status
 * @author RR42
 */

void key_release(GtkWidget *widget, GdkEvent *event, gpointer callback_data) {
    if (((GdkEventKey*)event)->keyval == GDK_Return)
        gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_OK);
}

/**
 * This asks password
 * @author RR42
 * @return password
 */

char* rr42su_ask_password() {
    gint response; // window response
    //*// A dialog with buttons
    GtkWidget *dialog = gtk_dialog_new_with_buttons("RR42 GTK+2 su frontend.", //TODO: more functionality
                        NULL,
                        0,
                        GTK_STOCK_CANCEL,
                        GTK_RESPONSE_CANCEL,
                        GTK_STOCK_OK,
                        GTK_RESPONSE_OK,
                        NULL);
        gtk_window_set_default_size(GTK_WINDOW(dialog), 300, 90);// Set size
        gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); // and position
        gtk_container_set_border_width(GTK_CONTAINER(dialog), 3); // border width = 3
        g_signal_connect(G_OBJECT(dialog), "key_release_event", G_CALLBACK(key_release), NULL);
        
        //gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
        
        //*// Widget that splits label and text field
        GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
            //*// Widget that aligns the label
            GtkWidget *halign = gtk_alignment_new(0, 0, 0, 1); // leftside
                GtkWidget *label = gtk_label_new("Enter root password:");
                gtk_container_add(GTK_CONTAINER(halign), label);
            gtk_container_add(GTK_CONTAINER(content_area), halign); // label inside a layout

            GtkWidget *entry = gtk_entry_new();
                gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
            gtk_container_add(GTK_CONTAINER(content_area), entry);
    gtk_widget_show_all(dialog);
    
    // make text field become focused
    gtk_widget_grab_focus(entry);
    
    response = gtk_dialog_run(GTK_DIALOG(dialog));
    //gchar *password = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
    gchar *password = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
    // FIXME: is it necessary
    gtk_entry_set_text(GTK_ENTRY(entry), "");
    
    switch (response) {
        case GTK_RESPONSE_CANCEL:
        case GTK_RESPONSE_DELETE_EVENT:
        case GTK_RESPONSE_NONE:
            exit(0);
    }
    
    gtk_widget_destroy(dialog);
    
    // Wait until widget is deleted. Without this window will not be closed
    while (gtk_events_pending())
        gtk_main_iteration();
    return password;
}

/**
 * This asks password and writes it to the file
 * referenced by the file descriptor
 * @author RR42
 * @param fd: file descriptor
 */

void rr42su_ask_password_and_write(int fd) {
    gint target_uid = 0;
    gint my_uid = getuid();

    char buf[256];
    read(fd, buf, 256); // Read "Password:"
    
    // If user is not root or target
    if (my_uid != target_uid && my_uid) {
        gchar *password = rr42su_ask_password();
        if (password == NULL) {
            return; //TODO: report an error in GUI
        }
        write(fd, password, strlen(password));
        write(fd, "\n", 1);

        //FIXME: is it necessary to fill the password with zeroes?
        int i = 0;
        while (password[i] != 0) {
            password[i] = 0;
            i++;
        }
        free(password);
    }
}
